﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Sector7.Restaurant.Modules.STAT.LocalService;
using Sector7.Restaurant.Modules.STAT.Biz;
using Sector7.Restaurant.Modules.STAT.Utility;
using Sector7.Framework.Enums;
using Sector7.Framework.Utility;

namespace Sector7.Restaurant.Modules.STAT.Controls
{
    class GraphElement
    {
        public GraphElement()
        {
            IsInitialized = false;
            Amount = 0;
            Charges = new List<RS_Charge>();
        }

        public bool IsInitialized { get; set; }
        public decimal Amount { get; set; }
        public List<RS_Charge> Charges { get; set; }
    }

    /// <summary>
    /// GraphControl.xaml 的交互逻辑
    /// </summary>
    public partial class GraphControl : UserControl
    {
        private double Y = 0;
        private double Y_MAXIMUM = 0;
        private const double X_INTERVAL = 30;
        private const double POINT_THICKNESS = 6;
        private const double GRAPH_THICKNESS = 2;
        private double PADDING_TOP = 0;
        private double PADDING_RIGHT = 0;

        private Color GRAPH_1 = Colors.Blue;
        private Color GRAPH_2 = Colors.Red;

        private Dictionary<string, GraphElement> _revenues = new Dictionary<string, GraphElement>();
        private Dictionary<string, GraphElement> _expenditures = new Dictionary<string, GraphElement>();

        private int _length;
        
        public GraphControl()
        {
            InitializeComponent();
        }

        public void LoadData(List<RS_Charge> charges, DateTime beginDate, DateTime endDate, GenerateDataType generateType)
        {
            _revenues.Clear();
            _expenditures.Clear();

            switch (generateType)
            {
                case GenerateDataType.ByDay:
                    _length = 8;
                    break;
                case GenerateDataType.ByMonth:
                    _length = 6;
                    break;
                case GenerateDataType.ByYear:
                    _length = 4;
                    break;
                default:
                    _length = 0;
                    break;
            }

            DrawX(beginDate, endDate, generateType);
            DrawY(charges);
            DrawGraph();

            ClientUtil.LoadItemsSource(dtgMain, _revenues.ElementAt(0).Value.Charges);
        }

        private void DrawX(DateTime beginDate, DateTime endDate, GenerateDataType generateType)
        {
            for (DateTime i = beginDate; i <= endDate; )
            {
                string occurTime = i.ToString("yyyyMMdd").Substring(0, _length);
                _revenues.Add(occurTime, new GraphElement());
                _expenditures.Add(occurTime, new GraphElement());

                switch (generateType)
                {
                    case GenerateDataType.ByDay:
                        i = i.AddDays(1);
                        break;
                    case GenerateDataType.ByMonth:
                        i = i.AddMonths(1);
                        break;
                    case GenerateDataType.ByYear:
                        i = i.AddYears(1);
                        break;
                    default:
                        break;
                }
            }
        }

        private void DrawY(List<RS_Charge> charges)
        {
            decimal maxAmount = 0;

            foreach (var charge in charges)
            {
                string occurTime = charge.OccurTime.ToString("yyyyMMdd").Substring(0, _length);

                GraphElement element = null;

                switch ((ChargeType)charge.ChargeType)
                {
                    case ChargeType.Revenues:
                        element = _revenues[occurTime];
                        break;
                    case ChargeType.Expenditures:
                        element = _expenditures[occurTime];
                        break;
                    default:
                        break;
                }

                element.Amount += charge.Amount;
                element.Charges.Add(charge);

                if (element.Amount > maxAmount)
                    maxAmount = element.Amount;
            }

            Y_MAXIMUM = (double)Math.Ceiling(maxAmount);
            Y = Math.Truncate(cvsMain.ActualHeight);
            PADDING_TOP = cvsMain.ActualHeight - Y;
        }

        private void DrawGraph()
        {
            cvsMain.Children.Clear();

            var datas = new List<Dictionary<string, GraphElement>>() { _revenues, _expenditures };

            int i = 0;
            foreach (var data in datas)
            {
                PointCollection points = new PointCollection();
                Color color = GRAPH_1;

                switch (i)
                {
                    case 0:
                        color = GRAPH_1;
                        break;
                    case 1:
                        color = GRAPH_2;
                        break;
                    default:
                        break;
                }

                int j = 0;
                foreach (var element in data.Values)
                {
                    double x = j * X_INTERVAL + 10;
                    double y = (Y_MAXIMUM == 0) ? Y : Y - ((double)element.Amount) / Y_MAXIMUM * Y;

                    Point point = new Point(x, y);

                    Ellipse ellipse = new Ellipse();
                    ellipse.Fill = new SolidColorBrush(color);
                    ellipse.Width = POINT_THICKNESS;
                    ellipse.Height = POINT_THICKNESS;
                    ellipse.Margin = new Thickness(point.X - POINT_THICKNESS / 2, point.Y - POINT_THICKNESS / 2, 0, 0);
                    ellipse.Tag = element;
                    ellipse.MouseEnter += new MouseEventHandler(Ellipse_MouseEnter);
                    ellipse.MouseDown += new MouseButtonEventHandler(Ellipse_MouseDown);

                    cvsMain.Children.Add(ellipse);

                    points.Add(point);

                    ++j;
                }

                Polyline polyline = new Polyline();
                polyline.StrokeThickness = GRAPH_THICKNESS;
                polyline.Stroke = new SolidColorBrush(color);
                polyline.Points = points;

                cvsMain.Children.Insert(i, polyline);

                ++i;
            }
        }

        private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
        {
            Ellipse ellipse = sender as Ellipse;
            GraphElement element = ellipse.Tag as GraphElement;

            ellipse.ToolTip = string.Format("金额：{0:0.00}", element.Amount);
        }

        private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
        {
            Ellipse ellipse = sender as Ellipse;
            GraphElement element = ellipse.Tag as GraphElement;

            ClientUtil.LoadItemsSource(dtgMain, element.Charges);
        }
    }
}
